学习率调度器

Note

到现在为止,我们都在关注优化算法,其实调整学习率和优化算法同样重要
一般如果想调参数,第一个就是学习率

为什么需要调整学习率

  1. 学习率大小很重要

  2. 学习率应当适当衰减,不然最后可能一直在最小值附近波动而不收敛

  3. 刚开始的时候学习率不宜过大,因为一开始参数是随机的,也就是学习率最好要有一个warmup阶段

常见的学习率调度器

from torch import nn
from torch.optim import lr_scheduler, Adam

# 先定义一个toy model及其对应的optimizer
net = nn.Sequential(
    nn.Linear(784, 100), nn.ELU(),
    nn.Linear(100, 10))
optimizer = Adam(net.parameters(), lr=0.05)

阶梯型 StepLR

# 调度器是用来装饰optimizer的
# 每隔step_size个epoch,学习率乘以gamma
# lr = 0.05     if epoch < 30
# lr = 0.005    if 30 <= epoch < 60
# lr = 0.0005   if 60 <= epoch < 90
scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

调度器使用的方式:

for epoch in range(10):
    train(...)
    val_loss = validate(...)
    scheduler.step()

指数衰减 ExponentialLR

\[ \mathrm{lr} = \mathrm{lr}\_{\mathrm{init}} * \gamma^{epoch} \]
scheduler = lr_scheduler.ExponentialLR(optimizer, gamma=0.9)

自适应学习率 ReduceLROnPlateau

当某项指标不再变化时,调整学习率,这是非常实用的策略

比如说 loss 不再下降时调整学习率;或者 accuracy 不再上升时调整学习率

# mode: min对应越低越好的指标如loss,max对应越高越好的指标如accuracy
# factor: 每次调整为:lr = lr * factor
# patience: number of epochs with no improvement after which learning rate will be reduced
# cooldown: 每次调整后经过多少个epoch再重启监测
# min_lr: 最小学习率
# step时需指定指标,比如说 plateau_scheduler.step(val_loss)
plateau_sheduler = lr_scheduler.ReduceLROnPlateau(optimizer, 
                                           mode='min', 
                                           factor=0.2,
                                           patience=5,
                                           cooldown=3,
                                           min_lr=1e-3)

Note

还有其它的调度器如先warmup后衰减的OneCycleLR、周期性升高降低的CycleLR、自定义调度器LambdaLR
还没太搞明白,先这样吧^_^